<html id="data_app" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>データ駆動型アプリケーション</title>
    <othercredit role="translator">
      <firstname></firstname>
      <surname>kmine</surname>
      <contrib>2006/07/03　翻訳初版</contrib>
    </othercredit>
</head>
<body>

<h1>データ駆動型アプリケーションの構築</h1>
<h2>はじめに</h2>

<p>このチュートリアルでは、完全に機能する電話帳アプリケーションを作ります。このアプリケーションは連絡先のリストを表示し、追加、編集、削除ができます。</p>

<ul>
	<li>このチュートリアルの最初では、データソースとして静的な XML 文書を使います。</li>
	<li>第 2 部では、データソースとして関係データベースを使います。</li>
</ul>

<img class="illustration" src="img/d_t_datapp_1.gif" width="399" height="312"/>


<h2>データの取得</h2>

<p>Laszlo アプリケーションでデータを表示するには 2 つの大きなステップがあります。</p>

<ul>
    <li>データセットを定義する</li>
    <li>ユーザインターフェイスのコンポーネントにデータをバインドする</li>
</ul>

<example title="データセットの定義 : phonebook.lzx">
&lt;canvas height="50" width="700" bgcolor="#D4D0C8"&gt;
  &lt;dataset name="dset"&gt;
    &lt;phonebook&gt;
      &lt;contact category="friends"&gt;
        &lt;firstName&gt;John&lt;/firstName&gt;
        &lt;lastName&gt;Smith&lt;/lastName&gt;
        &lt;phone&gt;617-536-7855&lt;/phone&gt;
        &lt;email&gt;jsmith@mail.com&lt;/email&gt;
      &lt;/contact&gt;
    &lt;/phonebook&gt;
  &lt;/dataset&gt;
  &lt;view name="list"&gt;
    &lt;simplelayout axis="x"/&gt;
    &lt;!-- 1 --&gt;
    &lt;text datapath="dset:/phonebook/contact/firstName/text()"/&gt;
    &lt;text datapath="dset:/phonebook/contact/lastName/text()"/&gt;
    &lt;text datapath="dset:/phonebook/contact/phone/text()"/&gt;
    &lt;text datapath="dset:/phonebook/contact/email/text()"/&gt;
    &lt;!-- 2 --&gt;
    &lt;text datapath="dset:/phonebook/contact/@category"/&gt; 
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<!--
<img src="img/d_t_datapp_2.gif" width="433" height="37" alt="" border="0"/>
-->
<h3>データセットの使用</h3>
<p>データセットは、アプリケーションのデータを含む XML 文書を表します。 dataset タグは (この例のように) データを埋め込むことができ、また後にこのチュートリアルで述べるように外部リソースを指すようにすることもできます。一つのアプリケーションに複数のデータセットを定義することもできます。データセットは OpenLaszlo のデータバインディング API の基礎です。</p>


<h3>XPath とデータバインディング API の使用</h3>
<p>データバインディング API により、ユーザインターフェイスコンポーネントをデータと自動的に配置させることができます。コンポーネントがどのデータを表示するべきかを指定するため、ユーザインターフェイスコンポーネントに対して datapath 属性を用います。 datapath 属性の値は XPath 式です。 XML 文書の階層構造をたどるのに、 XPath 式では単純な URL 的記法を用います。その式は、後ろにコロンを置いたデータセットの名前と、必要なタグへのパスから成ります。タグのデータ値を表示するには /text() を使い (コメント 1 から 2) 、タグの属性値を表示するには @属性名 を使います (コメント 2) 。</p>
 
<h3>相対アドレス参照</h3>
<p>もっと簡単にコードを読んだり維持したりできるようにするために、コンテナ view を特定のノードにバインドして、相対アドレスを使ってその view 内にユーザインターフェイスコンポーネントをバインドすることができます。</p>


<example extract="false">
&lt;view name="list" datapath="dset:/phonebook/contact"&gt;
  &lt;simplelayout axis="x"/&gt;
  &lt;text datapath="firstName/text()"/&gt;
  &lt;text datapath="lastName/text()"/&gt;
  &lt;text datapath="phone/text()"/&gt;
  &lt;text datapath="email/text()"/&gt;
  &lt;text datapath="@category"/&gt;
&lt;/view&gt;
</example>


<h3>複数列のデータの使用</h3>
<p>Laszlo は複数行のデータを操作したり表示したりするのを簡単にします。 XPath 式が XML 文書のノードを 1 つ以上指す場合、結合したユーザインターフェイスコンポーネントは各ノードごとに繰り返されます。</p>

<example title="binding data to views">
&lt;canvas height="50" width="700" bgcolor="#D4D0C8"&gt;
  &lt;dataset name="dset"&gt;
    &lt;phonebook&gt;
      &lt;contact category="friends"&gt;
        &lt;firstName&gt;John&lt;/firstName&gt;
        &lt;lastName&gt;Smith&lt;/lastName&gt;
        &lt;phone&gt;617-536-7855&lt;/phone&gt;
        &lt;email&gt;jsmith@mail.com&lt;/email&gt;
      &lt;/contact&gt;
      &lt;contact category="business"&gt;
        &lt;firstName&gt;Mary&lt;/firstName&gt;
        &lt;lastName&gt;Jones&lt;/lastName&gt;
        &lt;phone&gt;415-534-1186&lt;/phone&gt;
        &lt;email&gt;mjones@mail.com&lt;/email&gt;
      &lt;/contact&gt;
      &lt;contact category="friends"&gt;
        &lt;firstName&gt;Lisa&lt;/firstName&gt;
        &lt;lastName&gt;Brown&lt;/lastName&gt;
        &lt;phone&gt;212-423-1132&lt;/phone&gt;
        &lt;email&gt;lbrown@mail.com&lt;/email&gt;
      &lt;/contact&gt;
    &lt;/phonebook&gt;
  &lt;/dataset&gt;
  &lt;simplelayout axis="y"/&gt;
  &lt;view name="list" datapath="dset:/phonebook/contact"&gt;
    &lt;simplelayout axis="x"/&gt;
    &lt;!-- 1 --&gt;
    &lt;text datapath="firstName/text()"/&gt;
    &lt;text datapath="lastName/text()"/&gt;
    &lt;text datapath="phone/text()"/&gt;
    &lt;text datapath="email/text()"/&gt;
    &lt;text datapath="@category"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<!-- 
<img src="img/d_t_datapp_3.gif" width="455" height="41" alt="" border="0"/>
-->
<p>XPath は式で取得されるノードの数を制限するために、 1 ベースのインデックス記法もサポートします。 list view (コメント 1) の datapath 属性で、次のような XPath 式で試せます。</p>

<table>
  <tr>
    <th>XPath 式</th>
    <th>結果</th>
  </tr>
  <tr>
    <td><code>dset:/phonebook/contact</code></td>
    <td><p>全ての contact ノード</p></td>
  </tr>
  <tr>
    <td><code>dset:/phonebook/contact[1]</code></td>
    <td><p>最初の contact ノードのみ</p></td>
  </tr>
  <tr>
    <td><code>dset:/phonebook/contact[2-3]</code></td>
    <td><p>2 から 3 の contact ノード</p></td>
  </tr>
  <tr>
    <td><code>dset:/phonebook/contact[2-]</code></td>
    <td><p>2 以降の contact ノード</p></td>
  </tr>
  <tr>
    <td><code>dset:/phonebook/contact[-2]</code></td>
    <td><p>2 までの contact ノード (2 を含む)</p></td>
  </tr>
</table>

<h3>外部 XML 文書の使用</h3>

<p>この時点では、 phonebook アプリケーションのデータはアプリケーションのソースコードに埋め込まれています。こういうのは、アプリケーションで再利用されない固定情報には適切です。でも大抵の場合では、データをアプリケーションのソースコードの外に出すのがより良いアプローチです。</p>

<p>最初は、電話帳アプリケーションのデータを含む phonebook.xml という XML 文書は作ります。</p>


<pre class="code">
<b>phonebook.xml:</b>
&lt;phonebook&gt;
  &lt;contact firstName="John" lastName="Smith" phone="617-536-7855" 
           email="jsmith@mail.com"/&gt;
  &lt;contact firstName="Lisa" lastName="Jones" phone="415-225-8743" 
           email="ljones@mail.com"/&gt;
  &lt;contact firstName="Mary" lastName="Brown" phone="212-665-5211" 
           email="mbrown@mail.com"/&gt;
&lt;/phonebook&gt;
</pre>


<p>電話帳アプリケーションのソースコードからデータを削除して、 phonebook.xml ファイルへの dataset 参照を作ります。</p>


<example title="外部データセットを使う">
&lt;canvas height="50" width="700" bgcolor="#D4D0C8"&gt;
  &lt;dataset name="dset" src="../phonebook.xml"/&gt;
  &lt;simplelayout axis="y"/&gt;
  &lt;view name="list" datapath="dset:/phonebook/contact"&gt;
    &lt;simplelayout axis="x"/&gt;
    &lt;text datapath="@firstName"/&gt;
    &lt;text datapath="@lastName"/&gt;
    &lt;text datapath="@phone"/&gt;
    &lt;text datapath="@email"/&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>


<note>上の例で、 <code>phonebook.lzx</code> と <code>phonebook.xml</code> は同じディレクトリにあります <fixme>fixme</fixme>。必要なファイルを参照する際に、完全修飾名でも別の相対 URL でも使うことができます。</note>


<h2>データセットの更新</h2>

<p>この時点では、電話帳アプリケーションは連絡先リストを表示することができるだけです。このセクションでは、アプリケーションに更新と削除機能を追加します (このチュートリアルの後の方で新しい連絡先を挿入するようにします) 。最初のステップでは、ユーザが連絡先を修正・削除できるデータ入力ビュー (コメント 2 から 3) をアプリケーションに与えます。デフォルトではこのビューを不可視にします。list view (コメント 1) に定義された onclick イベントが、連絡先がクリックされたときに updateContact view を表示／非表示するトグルとして働きます。</p>

<example title="&lt;onclick&gt; メソッドを使ってデータを更新">
&lt;canvas height="200" width="700" bgcolor="#D4D0C8"&gt;
  &lt;dataset name="dset" src="../phonebook.xml"/&gt;
  &lt;simplelayout axis="y"/&gt;
  &lt;view datapath="dset:/phonebook/contact"&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;!-- 1 --&gt;
    &lt;view name="list" 
          onclick="parent.updateContact.setVisible(!parent.updateContact.visible);"&gt;
      &lt;simplelayout axis="x"/&gt;
      &lt;text datapath="@firstName"/&gt;
      &lt;text datapath="@lastName"/&gt;
      &lt;text datapath="@phone"/&gt;
      &lt;text datapath="@email"/&gt;
    &lt;/view&gt;
    &lt;view name="updateContact" visible="false" x="20" height="120"&gt;
      &lt;text y="10"&gt;First Name:&lt;/text&gt;
      &lt;!-- 2 --&gt;
      &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
      &lt;text y="35"&gt;Last Name:&lt;/text&gt;
      &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
      &lt;text y="60"&gt;Phone:&lt;/text&gt;
      &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
      &lt;text y="85"&gt;Email:&lt;/text&gt;
      &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
      &lt;button width="80" x="200" y="10"&gt;Update
        &lt;!-- 2a --&gt;
        &lt;method event="onclick"&gt;
            parent.parent.datapath.updateData();
        &lt;/method&gt;
      &lt;/button&gt;
      &lt;button width="80" x="200" y="40"&gt;Delete
        &lt;!-- 2b --&gt;
        &lt;method event="onclick"&gt;
            parent.parent.datapath.deleteNode();
        &lt;/method&gt;
      &lt;/button&gt;
      &lt;!-- 3 --&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>

<!--
<img src="img/d_t_datapp_4.gif" width="397" height="163" alt="" border="0"/>
-->
<h3>データセットの更新</h3>

<p>ユーザインターフェイスコンポーネントに結びつけられて入力された情報に基づいてデータセットを更新するには、 datapath オブジェクトの updateData() メソッドを実行します (コメント 2a) 。 updateData() は単に結合されているユーザインターフェイスコンポーネントからデータをデータセットにコピーするだけです。</p>


<h3>データセットのノードの削除</h3>

<p>データセットのノードを削除するには、 datapath オブジェクトの deleteNode() メソッドを実行します (コメント 2b) 。</p>



<h2>データポインタを使う</h2>

<h3>データを新しいノードに結合する</h3>

<p>データポインタをどう用いてノードをデータセットに追加するかを見る前に、ユーザが新しい連絡先を入力できるユーザインターフェイスをセットアップします。</p>

<example title="新規連絡先の追加用の UI ">
&lt;canvas height="400" width="700" bgcolor="#D4D0C8"&gt;
  &lt;dataset name="dset" src="../phonebook.xml"/&gt;
  &lt;simplelayout axis="y"/&gt;
  &lt;view&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;!-- 1 --&gt;
    &lt;text onclick="parent.newContact.setVisible(!parent.newContact.visible);"&gt;New Entry...&lt;/text&gt;
    &lt;!-- 2 --&gt;
    &lt;view name="newContact" datapath="new:/contact" 
          visible="false" x="20" height="120"&gt;
      &lt;text y="10"&gt;First Name:&lt;/text&gt;
      &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
      &lt;text y="35"&gt;Last Name:&lt;/text&gt;
      &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
      &lt;text y="60"&gt;Phone:&lt;/text&gt;
      &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
      &lt;text y="85"&gt;Email:&lt;/text&gt;
      &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
      &lt;button width="80" x="200" y="10"&gt;Add
        &lt;method event="onclick"&gt;
          parent.parent.datapath.updateData();
        &lt;/method&gt;
      &lt;/button&gt;
    &lt;/view&gt;
    &lt;!-- 3 --&gt;
  &lt;/view&gt;
  &lt;view datapath="dset:/phonebook/contact"&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;view name="list" 
          onclick="parent.updateContact.setVisible(!parent.updateContact.visible);"&gt;
      &lt;simplelayout axis="x"/&gt;
      &lt;text datapath="@firstName"/&gt;
      &lt;text datapath="@lastName"/&gt;
      &lt;text datapath="@phone"/&gt;
      &lt;text datapath="@email"/&gt;
    &lt;/view&gt;
    &lt;view name="updateContact" visible="false" x="20" height="120"&gt;
      &lt;text y="10"&gt;First Name:&lt;/text&gt;
      &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
      &lt;text y="35"&gt;Last Name:&lt;/text&gt;
      &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
      &lt;text y="60"&gt;Phone:&lt;/text&gt;
      &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
      &lt;text y="85"&gt;Email:&lt;/text&gt;
      &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
      &lt;button width="80" x="200" y="10"&gt;Update
        &lt;method event="onclick"&gt;
          parent.parent.datapath.updateData();
        &lt;/method&gt;
      &lt;/button&gt;
      &lt;button width="80" x="200" y="40"&gt;Delete
        &lt;method event="onclick"&gt;
          parent.parent.datapath.deleteNode();
        &lt;/method&gt;
      &lt;/button&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<!--
<img src="img/d_t_datapp_5.gif" width="415" height="196" alt="" border="0"/>
-->
<p>ユーザが連絡先リストのトップにある "New Entry" テキスト (コメント 1) をクリックすると、 newContact view (コメント 2 から 3) が表示されます。 newContact view は、 datapath 属性が "new:/contact" であることを除いて updateContact view と同じです。空の連絡先ノードで、新規のテンポラリデータセットを作ります。</p>

<p>アプリケーションを動かすと、 Add ボタンをクリックしたときには連絡先リストに新規の連絡先が追加されていないことに気づくでしょう。まだテンポラリデータセットで定義した新規連絡先ノードをメインのデータセット (dset) に追加しなければなりません。この操作を行うのに、データポインタを使います。</p>


<h3>データポインタの使用</h3>
<p>データポインタは、データセットの特定のノードへのポインタです。一般にはデータをプログラムで操作する必要があるときに、データポインタを使います。データポインタは一度にデータセットのノードを 1 つ指せるだけでなく、複数のデータポインタを定義してデータセットのいろんなノードを指すこともできます。</p>

<p>新規連絡先ノードを dset データセットに追加するコードを加えて、Add ボタンのイベントハンドラを修正しましょう。</p>

<pre class="code">
&lt;method event="onclick"&gt;
  parent.datapath.updateData();
  var dp=canvas.datasets.dset.getPointer();   // 1
  dp.selectChild();                           // 2
  dp.addNodeFromPointer(parent.datapath);     // 3
  parent.setDatapath("new:/contact");         // 4
&lt;/method&gt;
</pre>

<table>
  <tr>
    <th>コメント</th>
    <th>説明</th>
  </tr>
  
  <tr>
    <td><span class="regular">1</span></td>
    <td><span class="regular">dset データセットのデータポインタを取得する。</span></td>
  </tr>

  <tr>
    <td><span class="regular">2</span></td>
    <td><span class="regular">データポインタが dset の最初の子ノードを指すようにする。それは &lt;phonebook&gt; タグです。</span></td>
  </tr>

  <tr>
    <td><span class="regular">3</span></td>
    <td><span class="regular">phonebook ノードに新規連絡先ノードを追加する。</span></td>
  </tr>

  <tr>
    <td><span class="regular">4</span></td>
    <td><span class="regular">newContact view のデータパスを再初期化する。</span></td>
  </tr>
</table>

<example title="&lt;onclick&gt; メソッドを使って新規連絡先を追加する">
&lt;canvas height="400" width="700" bgcolor="#D4D0C8"&gt;
  &lt;dataset name="dset" src="../phonebook.xml"/&gt;
  &lt;simplelayout axis="y"/&gt;
  &lt;view&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;!-- 1 --&gt;
    &lt;text onclick="parent.newContact.setVisible(!parent.newContact.visible);"&gt;New Entry...&lt;/text&gt;
    &lt;!-- 2 --&gt;
    &lt;view name="newContact" datapath="new:/contact" 
          visible="false" x="20" height="120"&gt;
      &lt;text y="10"&gt;First Name:&lt;/text&gt;
      &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
      &lt;text y="35"&gt;Last Name:&lt;/text&gt;
      &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
      &lt;text y="60"&gt;Phone:&lt;/text&gt;
      &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
      &lt;text y="85"&gt;Email:&lt;/text&gt;
      &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
      &lt;button width="80" x="200" y="10"&gt;Add<em>
        &lt;method event="onclick"&gt;
           parent.datapath.updateData();
           var dp=canvas.datasets.dset.getPointer();   
           dp.selectChild();                           
           dp.addNodeFromPointer(parent.datapath);     
           parent.setDatapath("new:/contact");         
         &lt;/method&gt;</em>
      &lt;/button&gt;
    &lt;/view&gt;
    &lt;!-- 3 --&gt;
  &lt;/view&gt;
  &lt;view datapath="dset:/phonebook/contact"&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;view name="list" 
          onclick="parent.updateContact.setVisible(!parent.updateContact.visible);"&gt;
        &lt;simplelayout axis="x"/&gt;
        &lt;text datapath="@firstName"/&gt;
        &lt;text datapath="@lastName"/&gt;
        &lt;text datapath="@phone"/&gt;
        &lt;text datapath="@email"/&gt;
    &lt;/view&gt;
    &lt;view name="updateContact" visible="false" x="20" height="120"&gt;
      &lt;text y="10"&gt;First Name:&lt;/text&gt;
      &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
      &lt;text y="35"&gt;Last Name:&lt;/text&gt;
      &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
      &lt;text y="60"&gt;Phone:&lt;/text&gt;
      &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
      &lt;text y="85"&gt;Email:&lt;/text&gt;
      &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
      &lt;button width="80" x="200" y="10"&gt;Update
        &lt;method event="onclick"&gt;
          parent.parent.datapath.updateData();
        &lt;/method&gt;
      &lt;/button&gt;
      &lt;button width="80" x="200" y="40"&gt;Delete
        &lt;method event="onclick"&gt;
          parent.parent.datapath.deleteNode();
        &lt;/method&gt;
      &lt;/button&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
	

<h2>クラスを使う</h2>

<p>多分気が付いたと思いますが、 newContact view と updateContact view のコードの多くは同じです。これは、クラスに一般的コードを抽象化する機会のよい印です。このアプローチは再利用を推進し、アプリケーションの一貫性を保証します。この場合は、以下の一般的な contactview クラスを作ります。</p>

<pre class="code">
&lt;class name="contactview" extends="view" visible="false" x="20" height="120"&gt;
  &lt;text y="10"&gt;First Name:&lt;/text&gt;
  &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
  &lt;text y="35"&gt;Last Name:&lt;/text&gt;
  &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
  &lt;text y="60"&gt;Phone:&lt;/text&gt;
  &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
  &lt;text y="85"&gt;Email:&lt;/text&gt;
  &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
&lt;/class&gt;
</pre>


<p>contactview クラスを使って Phonebook アプリケーションを修正すると次のようになります。</p>

<example title="Using &quot;contactview&quot; class">
&lt;canvas height="200" width="700" bgcolor="#D4D0C8" &gt;
  &lt;dataset name="dset" src="../phonebook.xml"/&gt; <em>
  &lt;class name="contactview" extends="view" visible="false" x="20" height="120"&gt;
    &lt;text y="10"&gt;First Name:&lt;/text&gt;
    &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
    &lt;text y="35"&gt;Last Name:&lt;/text&gt;
    &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
    &lt;text y="60"&gt;Phone:&lt;/text&gt;
    &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
    &lt;text y="85"&gt;Email:&lt;/text&gt;
    &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
  &lt;/class&gt;</em>
  &lt;simplelayout axis="y"/&gt;
  &lt;view&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;text onclick="parent.newContact.setVisible(!parent.newContact.visible);"&gt;New Entry...&lt;/text&gt;
    &lt;contactview name="newContact" datapath="new:/contact"&gt;
      &lt;button width="80" x="200" y="10"&gt;Add
        &lt;method event="onclick"&gt;
          parent.datapath.updateData();
          var dp=canvas.datasets.dset.getPointer();
          dp.selectChild();
          dp.addNodeFromPointer( parent.datapath );
          parent.setVisible(false);
          parent.setDatapath("new:/contact");
        &lt;/method&gt;
      &lt;/button&gt;
    &lt;/contactview&gt;
  &lt;/view&gt;
  &lt;view datapath="dset:/phonebook/contact"&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;view name="list" onclick="parent.updateContact.setVisible(!parent.updateContact.visible);"&gt;
      &lt;simplelayout axis="x"/&gt;
      &lt;text datapath="@firstName"/&gt;
      &lt;text datapath="@lastName"/&gt;
      &lt;text datapath="@phone"/&gt;
      &lt;text datapath="@email"/&gt;
    &lt;/view&gt;
    &lt;contactview name="updateContact"&gt;
      &lt;button width="80" x="200" y="10"&gt;Update
        &lt;method event="onclick"&gt;
          parent.parent.datapath.updateData();
        &lt;/method&gt;
      &lt;/button&gt;
      &lt;button width="80" x="200" y="40"&gt;Delete
        &lt;method event="onclick"&gt;
          parent.parent.datapath.deleteNode();
        &lt;/method&gt;
      &lt;/button&gt;
    &lt;/contactview&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>


<h2>データベースを使う</h2>

<p>このチュートリアルの最初のパートで、 OpenLaszlo アプリケーションにデータを提供する 2 つのアプローチを示しました。</p>

<ol>
	<li>アプリケーションのソースコードにデータを埋め込む</li>
	<li>外部 XML 文書を使う</li>
</ol>

<p>データセットは、データベース、 Web サービス、レガシシステム等からの情報を使って動的に XML を生成するサーバサイドスクリプトを指すこともできます。</p>

<p>このセクションでは、 Phonebook アプリケーションをデータベースで動作するように修正します。</p>

<ul>
	<li>連絡先リストはデータベーステーブルから取得されます。</li>
	<li>更新、削除、挿入の操作はデータベースに適用されます。</li>
</ul>

<p>Laszlo は、 XML を生成できるサーバサイト技術と統合します。 Java Servlets, JavaServer Pages (JSP), CGI スクリプト, PHP スクリプト, Active Server Pages (ASP), などです。 </p>

<p>このチュートリアルでは、サーバサイド技術として JavaServer Pages を使います。</p>


<h3>データベースのセットアップ</h3>
<p>このセクションを行うには、リレーショナルデータベースと JDBC ドライバが必要です。</p>

<ol>
	<li>contact という名のテーブルを作る。</li>
	<li>email, first_name, last_name, phone の 4 つの varchar(20) を定義する。データベースが varchar データ型をサポートしていないなら、他のテキストベースのデータ型を選択する。</li>
	<li>email を contact テーブルのプライマリキーに指定する。</li>
	<li>サンプルデータを入力する。</li>
</ol>



<h3>データベースからのデータ取得</h3>


<h4>JSP の作成</h4>

<p>最初のステップは、 contact テーブルの連絡先を表す XML 文書を生成する JavaServer Page を作ることです。</p>

<pre class="code">
<b>getcontacts.jsp:</b>

&lt;%@ page import="java.sql.*"%&gt;
&lt;phonebook&gt;
&lt;%
    Connection connection = null;
    try {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");  // 1
        connection = DriverManager.getConnection("jdbc:odbc:laszlosamples"); // 2
        Statement stmt = connection.createStatement();
        ResultSet rs = stmt.executeQuery("select * from contact");
        while (rs.next()) {
    %&gt;
            &lt;contact firstName="&lt;%= rs.getString("first_name")%&gt;"
                           lastName="&lt;%= rs.getString("last_name")%&gt;"
                           phone="&lt;%= rs.getString("phone")%&gt;"
                           email="&lt;%= rs.getString("email")%&gt;"/&gt;
    &lt;%
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            connection.close();
        } catch (SQLException e) {
        }
    }
%&gt;
&lt;/phonebook&gt;
</pre>



<p>この例では、データベースへのアクセスに Sun の JDBC-ODBC ブリッジを使用しています。</p>


<ul>
	<li>コメント 1: 使用している JDBC ドライバで sun.jdbc.odbc.JdbcOdbcDriver を置き換えてください。</li>
	<li>コメント 2: ドライバが要求する JDBC URL で jdbc:odbc:laszlosamples を置き換えてください。</li>
</ul>



<h4>クライアントアプリケーションの変更</h4>

<p>クライアントアプリケーションを変更するのは簡単です。次のように dataset タグの属性を変更します。</p>

<pre class="code">
&lt;dataset name="dset" src="getcontacts.jsp" autorequest="true" type="http"/&gt;
</pre>


<table>
  <tr>
    <th>属性</th>
    <th>説明</th>
  </tr>

  <tr>
    <td><code>src="getcontacts.jsp"</code></td>
    <td><span class="regular">XML 文書を生成するサーバサイドプログラムへの完全修飾または相対 URL</span></td>
  </tr>

  <tr>
    <td><code>autorequest="true"</code></td>
    <td><span class="regular">アプリケーションがロードされたときに自動的にリクエストが送信されるべきであることを示す</span></td>
  </tr>

  <tr>
    <td><code>type="http"</code></td>
    <td><span class="regular">HTTP リクエストであることを示す。 type="http" は、 src 属性の値が http:// で始まる完全修飾 URL であるとき、暗黙に仮定されます。</span></td>
  </tr>

</table>



<h2>データの更新、削除、挿入</h2>

<h3>JSP の作成</h3>

<p>この例では、挿入、削除、更新を処理する 1 つの JSP を作ります。 </p>

<pre class="code">
<b>contactmgr.jsp:</b>

&lt;%@ page import="java.sql.*"%&gt;
&lt;%
    Connection connection = null;
    try {
        String action=request.getParameter("action");       // 3
        String firstName=request.getParameter("firstName");
        String lastName=request.getParameter("lastName");
        String phone=request.getParameter("phone");
        String email=request.getParameter("email");
        String pk=request.getParameter("pk");               // 4

        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        connection = DriverManager.getConnection("jdbc:odbc:laszlosamples"); // 1
        String sql="";      // 2

        if (action.equals("insert")) {
            sql="INSERT INTO contact (first_name, last_name, phone, email) VALUES ('"+
                                     firstName+"','"+lastName+"','"+phone+"','"+email+"')";
        } else if (action.equals("update")) {
            sql="UPDATE contact SET first_name='"+firstName+"', last_name='"+lastName+
                                     "', phone='"+phone+"', email='"+email+"' WHERE email='"+pk+"'";
        } else if (action.equals("delete")) {
            sql="DELETE FROM contact WHERE email='"+pk+"'";
        }

        Statement stmt = connection.createStatement();
        System.out.println("*** Executing SQL: "+sql);
        stmt.executeUpdate(sql);
%&gt;
        &lt;result&gt;success&lt;/result&gt;
&lt;%
    } catch (Exception e) {
        e.printStackTrace();
%&gt;
        &lt;result&gt;failure&lt;/result&gt;
&lt;%
    } finally {
        try {
            connection.close();
        } catch (SQLException e) {
        }
    }
%&gt;
</pre>


<p>この例ではデータベースへのアクセスに、 Sun の JDBC-ODBC ブリッジを使います。</p>

<ul>
	<li>コメント 1: 使用している JDBC ドライバで sun.jdbc.odbc.JdbcOdbcDriver を置き換えてください。</li>
	<li>コメント 2: ドライバが要求する JDBC URL で jdbc:odbc:laszlosamples を置き換えてください。</li>
</ul>

<p>JSP は OpenLaszlo クライアントアプリケーションから 6 個のパラメータが渡されるとしています (コメント 3 から 4) 。</p>

<table>
  <tr>
    <th>属性</th>
    <th>説明</th>
  </tr>

  <tr>
    <td><code>action</code></td>
    <td><span class="regular">行う操作。 "insert", "update", "delete" のどれかであること。</span></td>
</tr>

<tr>
    <td><code>firstName</code></td>
    <td><span class="regular">nsert か update のみで使用する。新規連絡先 (insert) 用の firstName の値か、または既存の連絡先 (update) の新しい firstName の値。</span></td>
</tr>

<tr>
    <td><code>lastName</code></td>
    <td><span class="regular">insert か update のみで使用する。新規連絡先 (insert) 用の lastName の値か、または既存の連絡先 (update) の新しい lastName の値。</span></td>
</tr>

<tr>
    <td><code>phone</code></td>
    <td><span class="regular">insert か update のみで使用する。新規連絡先 (insert) 用の phone の値か、または既存の連絡先 (update) の新しい phone の値。</span></td>
</tr>

<tr>
    <td><code>email</code></td>
    <td><span class="regular">insert か update のみで使用する。新規連絡先 (insert) 用の email の値か、または既存の連絡先 (update) の新しい email の値。</span></td>
</tr>

<tr>
    <td><code>Pk</code></td>
    <td><span class="regular">update か delete のみで使用する。変更する前の email (プライマリキー) の元の値。この値は UPDATE 文か DELETE 文の WHERE 句で必要となる。</span></td>
</tr>

</table>




<h3>クライアントアプリケーションの変更</h3>


<example extract="false">
&lt;canvas bgcolor="#D4D0C8"&gt;
  &lt;dataset name="dset" src="getcontacts.jsp" request="true" type="http"/&gt;
  &lt;!-- 1 --&gt;
  &lt;dataset name="dsSendData" request="false" src="contactmgr.jsp" type="http"/&gt;
  &lt;class name="contactview" extends="view" visible="false" x="20" height="120"&gt;
    &lt;!-- 2 --&gt;
    &lt;text name="pk" visible="false" datapath="@email"/&gt;
    &lt;text y="10"&gt;First Name:&lt;/text&gt;
    &lt;edittext name="firstName" datapath="@firstName" x="80" y="10"/&gt;
    &lt;text y="35"&gt;Last Name:&lt;/text&gt;
    &lt;edittext name="lastname" datapath="@lastName" x="80" y="35"/&gt;
    &lt;text y="60"&gt;Phone:&lt;/text&gt;
    &lt;edittext name="phone" datapath="@phone" x="80" y="60"/&gt;
    &lt;text y="85"&gt;Email:&lt;/text&gt;
    &lt;edittext name="email" datapath="@email" x="80" y="85"/&gt;
    &lt;method name="sendData" args="action"&gt;
      var d=canvas.datasets.dsSendData;                       // 3
      var p=new LzParam();                                    // 3a
      p.addValue("action", action, true);
      p.addValue("pk", pk.getText(), true);
      p.addValue("firstName", firstName.getText(), true);
      p.addValue("lastName", lastName.getText(), true);
      p.addValue("phone", phone.getText(), true);
      p.addValue("email", email.getText(), true);            // 3b
      d.setQueryString(p);                                   // 3c
      d.doRequest();                                         // 3d
    &lt;/method&gt;
    &lt;!-- 4 --&gt;
  &lt;/class&gt;
  &lt;simplelayout axis="y"/&gt;
  &lt;view&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;text onclick="parent.newContact.setVisible(!parent.newContact.visible);"&gt;New Entry...&lt;/text&gt;
    &lt;contactview name="newContact" datapath="new:/contact"&gt;
      &lt;button width="80" x="200" y="10"&gt;Add
        &lt;method event="onclick"&gt;
          parent.sendData("insert");                         // 5
          parent.datapath.updateData();
          var dp=canvas.datasets.dset.getPointer();
          dp.selectChild();
          dp.addNodeFromPointer( parent.datapath );
          parent.setVisible(false);
          parent.setDatapath("new:/contact");
        &lt;/method&gt;
      &lt;/button&gt;
    &lt;/contactview&gt;
  &lt;/view&gt;
  &lt;view datapath="dset:/phonebook/contact"&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;view name="list" onclick="parent.updateContact.setVisible(!parent.updateContact.visible);"&gt;
      &lt;simplelayout axis="x"/&gt;
      &lt;text datapath="@firstName"/&gt;
      &lt;text datapath="@lastName"/&gt;
      &lt;text datapath="@phone"/&gt;
      &lt;text datapath="@email"/&gt;
    &lt;/view&gt;
    &lt;contactview name="updateContact"&gt;
      &lt;button width="80" x="200" y="10"&gt;Update
        &lt;method event="onclick"&gt;
          parent.sendData("update");                      // 6
          parent.parent.datapath.updateData();
        &lt;/method&gt;
      &lt;/button&gt;
      &lt;button width="80" x="200" y="40"&gt;Delete
        &lt;method event="onclick"&gt;
          parent.sendData("delete");                      // 7
          parent.parent.datapath.deleteNode();
        &lt;/method&gt;
      &lt;/button&gt;
    &lt;/contactview&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>



<table>
  <tr>
    <th>コメント</th>
    <th>説明</th>
</tr>

<tr>
    <td><span class="regular">1</span></td>
    <td><span class="regular">新しいデータセットの dsSendData を定義する。このデータセットは、挿入、更新、削除したい連絡先の情報を送信するのに用いる。 request 属性は false に設定する。ユーザが Add, Update, Delete ボタンをクリックしたときに、サーバにリクエストが送信される。</span></td>
</tr>

<tr>
    <td><span class="regular">2</span></td>
    <td><span class="regular">オリジナルの連絡先のプライマリキーを保持するために、不可視の text コンポーネントを定義する。</span></td>
</tr>

<tr>
    <td><span class="regular">3 - 4</span></td>
    <td><span class="regular">contactview クラスに sendData() メソッドを追加する。このメソッドは、 dsSendData データセットを使い、 page パラメータとして連絡先情報を与えて contactmgr.jsp にリクエストを送信します。データに対してどの操作 (挿入、更新、削除) を行うのかをサーバに伝えるために、引数 action を取ります。</span></td>
</tr>

<tr>
    <td><span class="regular">3a</span></td>
    <td><span class="regular">新しい LzParam オブジェクトを作る。 LzParam オブジェクトは、 HTTP リクエストの一部としてサーバに送信された page パラメータをカプセル化する。</span></td>
</tr>

<tr>
    <td><span class="regular">3a to 3b</span></td>
    <td><span class="regular">サーバが欲しい 6 つの page パラメータ、action, firstName, lastName, phone, email, pk を指定して、LzParam オブジェクトを作ります。 addValue() メソッドの最初の引数は page パラメータの名前、2 番目の引数は page パラメータの値で、3 番目の引数は値が URI エンコードされて欲しいかどうかをしています。 </span></td>
</tr>

<tr>
    <td><span class="regular">3c</span></td>
    <td><span class="regular">dsSendData リクエスト用の page パラメータをセットする。注意 : page パラメータをカプセル化するのに常には LZParam を使う必要はない。例えば次の構文で dsSendData リクエスト用の page パラメータ をセットできる。</span>
<pre class="code">
d.setQueryString( { action: "action",
                    pk: pk.getText(),
                    firstName: firstName.getText(),
                    lastName: lastName.getText(),
                    phone: phone.getText(),
                    email: email.getText() } );
</pre>
<span class="regular">でもこの場合には page パラメータの値は URI エンコードされず、特殊文字を含んでいるときにはこのリクエストは失敗する。</span></td>
</tr>

<tr>
    <td><span class="regular">3d</span></td>
    <td><span class="regular">dataset タグの request 属性が false にセットされているときは、この方法でプログラムでリクエストを送信できる。</span></td>
</tr>

<tr>
    <td><span class="regular">5</span></td>
    <td><span class="regular">ユーザが Add ボタンをクリックすると、 insert 操作をリクエストする sendData() メソッドを実行する。</span></td>
</tr>

<tr>
    <td><span class="regular">6</span></td>
    <td><span class="regular">ユーザが Update ボタンをクリックすると、 update 操作をリクエストする sendData() メソッドを実行する。</span></td>
</tr>

<tr>
    <td><span class="regular">7</span></td>
    <td><span class="regular">ユーザが Delete ボタンをクリックすると、 delete 操作をリクエストする sendData() メソッドを実行する。</span></td>
</tr>
</table>


<h3>データポインタを使ってリクエストの成功／失敗をチェックする</h3>

<p>リクエストした操作が成功したとき、 <code>contactmgr.jsp</code> はシンプルな <code>success</code> xml 文書を返し、失敗したときは <code>failure</code> を返します。クライアントアプリケーションで success か failure かをチェックするため、 dsSendData データセットに ondata イベントのイベントハンドラを定義することができます。このイベントハンドラでは、データポインタを使って <code>tag</code> の値をチェックできます。</p>

<pre class="code">
&lt;datapointer xpath="dsSendData:/"&gt;
  &lt;method event="ondata"&gt;
    if (this.xpathQuery("result/text()") == "success") {
      Debug.write("Operation succeeded");
    } else {
      Debug.write("Operation failed");
    }
  &lt;/method&gt;
&lt;/datapointer&gt; 
</pre>

</body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
